package flp.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.KeyAdapter;
import java.io.Serializable;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * Struktura dano-nosna.
 * Struktura skladajaca sie z pol tekstowych.
 *
 * @author marek
 */
public class DataTable implements Serializable
{
    /**
     * Rozmiar x - liczba kolumn.
     */
    private int xSize;
    /**
     * Rozmiar y - liczba wierszy.
     */
    private int ySize;
    /**
     * Gdzie struktura jest zagniezdzona.
     */
    private transient JPanel root;
    /**
     * Pola tekstowe.
     */
    private JTextField[] cells;
    /**
     * Naglowki kolumn.
     */
    private JTextField[] horizontalH;
    /**
     * Naglowki wierszy.
     */
    private JTextField[] verticalH;
    /**
     * Komorka `krzyzowa` (zejscie naglowkow wierszy i kolumn).
     */
    private JTextField starterCell;
    // =============== USTAWIENIA WYGLĄDU ===============
    /** Czcionka naglowklw */
    private static final transient Font headlineFont = new Font("Tahoma", Font.BOLD, 12);
    /** Tlo komlrki startowej */
    private static final transient Color starterBgColor = new Color(39, 74, 166);
    /** Tlo naglowkow */
    private static final transient Color headlineBgColor = new Color(112, 130, 200);
    /** Tlo do cieniowania kolumn */
    private static final transient Color cellShadeBgColor = new Color(179, 199, 255);
    /** Wyrownywanie tekstu naglowkow */
    private static final transient int headlineAlignment = JTextField.CENTER;
    /** Wyrownywanie tekstu naglowkow */
    private static final transient int cellAlignment = JTextField.CENTER;
    private static final transient int cellHeight = 20;
    private static final transient int cellWidth = 30;

    public DataTable(DataTable copy, JPanel root)
    {
        this.root = root;
        this.xSize = copy.xSize;
        this.ySize = copy.ySize;
        this.cells = copy.cells;
        this.horizontalH = copy.horizontalH;
        this.verticalH = copy.verticalH;
        this.starterCell = copy.starterCell;
    }

    public DataTable(DataTable copy)
    {
        this(copy, copy.root);
    }

    /**
     * C-tor tablicy z danymi.
     * 
     * @param root Rodzic tablicy z danymi.
     * @param horizontalLabels Tablica z etykietami kolumn.
     * @param verticalLabels Tablica z etykietami wierszy.
     */
    public DataTable(JPanel root, String[] horizontalLabels, String[] verticalLabels)
    {
        this(null, horizontalLabels, verticalLabels, root);
    }

    public DataTable(DataTable copy, String[] horizontalLabels, String[] verticalLabels, JPanel root)
    {
        this.root = root;
        this.xSize = horizontalLabels.length;
        this.ySize = null == verticalLabels
                ? 1
                : verticalLabels.length;
        initialize(horizontalLabels, verticalLabels, copy);
    }
    
    public DataTable(DataTable copy, String[] horizontalLabels, String[] verticalLables)
    {
        this(copy, horizontalLabels, verticalLables, copy.root);
    }
    
    public DataTable(DataTable copy, String[] horizontalLabels, JPanel root)
    {
        this(copy, horizontalLabels, (String[])null, root);
    }

    public DataTable(DataTable copy, String[] horizontalLabels)
    {
        this(copy, horizontalLabels, (String[])null);
    }

    /**
     * C-tor tablicy z danymi.
     * 
     * @param root Rodzic tablicy z danymi.
     * @param headlineLabels Tablica z etykietami kolumn.
     */
    public DataTable(JPanel root, String[] headlineLabels)
    {
        this(root, headlineLabels, (String[])null);
    }

    public int getSizeX()
    {
        return xSize;
    }

    public int getSizeY()
    {
        return ySize;
    }

    /**
     * Inicjacja tablicy.
     * 
     * @param horizontalLabels Tablica z etykietami kolumn.
     * @param verticalLabels Tablica z etykietami wierszy.
     */
    private void initialize(String[] horizontalLabels, String[] verticalLabels,
            DataTable copy)
    {
        root.removeAll();
        root.setLayout(null == verticalLabels
                ? new GridLayout(ySize + 1, xSize)
                : new GridLayout(ySize + 1, xSize + 1));

        horizontalH = new JTextField[xSize];
        if (null != verticalLabels)
        {
            verticalH = new JTextField[ySize];
            for (int idx = 0; idx < ySize; idx++)
            {
                verticalH[idx] = new JTextField(verticalLabels[idx]);
                addHeader(verticalH[idx]);
            }
        }

        for (int idx = 0; idx < xSize; ++idx)
        {
            horizontalH[idx] = new JTextField(horizontalLabels[idx]);
            addHeader(horizontalH[idx]);
        }

        cells = new JTextField[xSize * ySize];
        for (int col = 0; col < xSize; ++col)
        {
            for (int row = 0; row < ySize; ++row)
            {
                String defaultText = (null != copy && col < copy.xSize && row < copy.ySize)
                        ? copy.cells[col * copy.ySize + row].getText()
                        : "0";
                cells[col * ySize + row] = new JTextField(defaultText);
                cells[col * ySize + row].setHorizontalAlignment(cellAlignment);
            }
        }

        //DODAWANIE KOMÓREK DO PANELU
        if (null != verticalLabels)
        {
            starterCell = new JTextField();
            starterCell.setEditable(false);
            starterCell.setBackground(starterBgColor);
            root.add(starterCell);
        }
        for (int idx = 0; idx < xSize; ++idx)
        {
            root.add(horizontalH[idx]);
        }
        if (null == verticalH)
        {
            for (int idx = 0; idx < xSize; ++idx)
            {
                root.add(cells[idx]);
            }
            return;
        }

        for (int hor = 0; hor < ySize; ++hor)
        {
            root.add(verticalH[hor]);
            for (int vert = 0; vert < xSize; ++vert)
            {
                root.add(cells[vert * ySize + hor]);
            }
        }

        for (int idx = 0; idx < xSize * ySize; idx++)
        {
            if ((idx / (xSize * ySize)) % 2 == 1)
            {
                cells[idx].setBackground(cellShadeBgColor);
            }
        }
    }

    private void addHeader(JTextField header)
    {
        header.setEditable(false);
        header.setBackground(headlineBgColor);
        header.setFont(headlineFont);
        header.setHorizontalAlignment(headlineAlignment);
        header.setPreferredSize(new Dimension(cellWidth, cellHeight));
    }

    public void addKeyListener(KeyAdapter listener)
    {
        for (int i = 0; i < xSize * ySize; ++i)
        {
            cells[i].addKeyListener(listener);
        }
    }

    public void addFocusListener(FocusAdapter listener)
    {
        for (int i = 0; i < xSize * ySize; ++i)
        {
            cells[i].addFocusListener(listener);
        }
    }

    public int getIntValue(int row, int col)
    {
        return getIntValue(row * xSize + col);
    }

    public int getIntValue(int idx)
    {
        try
        {
            return Integer.parseInt(cells[idx].getText());
        }
        catch (NumberFormatException nfe)
        {
            System.err.println(nfe.getStackTrace());
            return 0;
        }
    }

    public boolean getBoolValue(int row, int col)
    {
        return getIntValue(row, col) != 0;
    }

    public boolean getBoolValue(int idx)
    {
        return getIntValue(idx) != 0;
    }

    public double getDoubleValue(int row, int col)
    {
        return getDoubleValue(row * xSize + col);
    }

    public double getDoubleValue(int idx)
    {
        try
        {
            return Double.parseDouble(cells[idx].getText());
        }
        catch (NumberFormatException nfe)
        {
            System.err.println(nfe.getStackTrace());
            return 0.0;
        }
    }
}
